//
// BugzillaBackend.cs
//
// Copyright (C) 2008 Lukas Lipka <lukaslipka@gmail.com>
//

using System;
using System.Collections;
using System.IO;
using System.Xml;

using Dashboard;
using Dashboard.Util;
using Dashboard.Engine;

namespace Dashboard.Engine.Backends
{
	public class BugzillaBackend : Backend, IComponent
	{
		// FIXME: We shouldn't hardcode this
		private const string bugzilla_host = "http://bugzilla.gnome.org";

		public void Initialize () 
		{
			Engine.MessageBroker.Subscribe ("/event/*", typeof (ClueMessage), OnMessage);
		}

		public void Dispose ()
		{
			Engine.MessageBroker.Unsubscribe (OnMessage);
		}

		private void OnMessage (Message message)
		{
			Engine.Log.Debug ("Processing message");
			
			ClueMessage clue_message = message as ClueMessage;
			MatchMessage matches_message = new MatchMessage ();

			foreach (Clue clue in clue_message.Clues) {
				if (clue.Type != "db:bug")
					continue;
					
				if (String.IsNullOrEmpty (clue.Properties ["db:number"].Value))
					continue;

				string bug_number = clue.Properties ["db:number"].Value;
				string url = String.Format ("{0}/xml.cgi?id={1}", bugzilla_host, bug_number);

				StreamReader reader = WebpageFu.GetStream (url);

				XmlDocument xml = new XmlDocument ();
				xml.Load (reader);

				reader.Close ();
				
				Match match = XmlBugToMatch (xml, bug_number);
				match.Trigger = clue_message.Id;
				
				if (match != null)
					matches_message.Matches.Add (match);
			}

			if (matches_message.Matches.Count > 0)
				Engine.MessageBroker.Send (matches_message);
		}

		private Match XmlBugToMatch (XmlDocument xml, string bug_number)
                {
                        // Check if the bug was even found. If there wasn't a bug, there will be
                        // an error attribute on the /bug element that says NotFound if one didn't exist.

			XmlNode node = xml.SelectSingleNode ("/bugzilla/bug");
                        
			if (node == null || node.Attributes ["error"] != null)
				return null;
			
                        string bug_url = String.Format ("{0}/show_bug.cgi?id={1}", bugzilla_host, bug_number);
                        
			Match match = new Match ();
			match.Uri = new Uri (bug_url);
			match.Type = "db:bug";
			//match.Trigger = this.clue_message.Id;
			//match.Relevancy = (hit.Score * query_rule.Relevancy);			
			//match.Timestamp = hit.Timestamp;
			
			if (node ["bug_id"] != null)
				match.Properties.Add (new Property ("db:number",  node ["bug_id"].InnerText));

			if (node ["product"] != null)
				match.Properties.Add (new Property ("db:product", node ["product"].InnerText));

			if (node ["component"] != null)
				match.Properties.Add (new Property ("db:component", node ["component"].InnerText));

			if (node ["version"] != null)
				match.Properties.Add (new Property ("db:version", node ["version"].InnerText));

			if (node ["priority"] != null)
				match.Properties.Add (new Property ("db:priority", node ["priority"].InnerText));

			if (node ["bug_severity"] != null)
				match.Properties.Add (new Property ("db:severity", node ["bug_severity"].InnerText));

			if (node ["short_desc"] != null)
				match.Properties.Add (new Property ("dc:title",  node ["short_desc"].InnerText));

			if (node ["bug_status"] != null)
				match.Properties.Add (new Property ("db:status", node ["bug_status"].InnerText));

			if (node ["reporter"] != null)
				match.Properties.Add (new Property ("db:reporter", node ["reporter"].InnerText));

			if (node ["assigned_to"] != null)
				match.Properties.Add (new Property ("db:assigned", node ["assigned_to"].InnerText));

                        return match;
                }
		
		public string Name {
			get { return "Bugzilla"; }
		}

		public string Description {
			get { return ""; }
		}
	}
}
